package ray.mgocc.net;

import ray.mgocc.Store;
import ray.mgocc.Source;
import ray.mgocc.StoredSource;

import java.util.Map;
import java.util.Properties;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.params.HttpClientParams;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

//TODO interval implementation
//requestしてみて、302 html/index.htmlだったら、loginする。
//TODO http://www.konami.jp/mgo/とか他のsiteに飛ばされてたらfail.
public class Agent{
    private final static Log log = LogFactory.getLog(Agent.class);

    private Store store = null;
    final static String USER_AGENT = null;
    private HttpClient client = new HttpClient();
    void init(){
        if(null!=USER_AGENT){
            client.getParams().setParameter(HttpMethodParams.USER_AGENT,USER_AGENT);
        }
        client.getParams().setParameter(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS,true);
    }
    HttpClient getClient(){
        return this.client;
    }
    public Response post(String url,Properties params){
        Response response = null;
        PostMethod method = new PostMethod(url);
        for(Map.Entry param:params.entrySet()){
            method.addParameter((String)param.getKey(),(String)param.getValue());
        }
        try{
            int statusCode = client.executeMethod(method);
            log.info(statusCode+" "+url);
            response = new Response(method);
        }catch(Exception e){
            log.error(e);
            throw new RuntimeException("post error.",e);
        }
        return response;
    }
    public Response get(String url){
        Response response = null;
        try {
            HttpMethod method = new GetMethod(url);
            method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                                            new DefaultHttpMethodRetryHandler(3, false));
            int statusCode = client.executeMethod(method);
            log.info(statusCode+" "+url);
            response = new Response(method);
        } catch (Exception e) {
            log.error(e);
            throw new RuntimeException(e);
        }
        return response;
    }
    private void log(String url,List<Header> headers){
        for(Header header:headers){
            log.debug("Header "+header);
        }
    }
    public void setStore(Store store){
        this.store = store;
    }
    /**
     * requestを行います。
     * request中にnameが指定されていると、Storeが可能です。
     */
    public Source request(Request request){
        Source response = null;
        String name = request.getName();
        if(null!=name){
            if(null != store){
                // read store.
                response = store.read(name);
                if(null!=response){
                    log.info("read store:"+name);
                }
            }
        }

        if(null==response){
            Method method = request.getMethod();
            if(Method.GET == method){
                response = get(request.getUri());
            }else if(Method.POST == method){
                response = post(request.getUri(),request.getParam());
            }else{
                throw new RuntimeException("unknown method."+method);
            }

            if(null!=response){
                store.write(name,response);
            }

            if(null!=name){
                Source local = new StoredSource(store.getFile(name));
                response = new ComplexSource(response,local);
            }
        }

        return response;
    }
}
